﻿using System;
using System.Security.Authentication;
using System.Security.Cryptography;
using System.Text;

namespace CommonFramework.Time
{
    public static class HashUtil
    {
        private static HashAlgorithm CreateAlgoByType(HashAlgorithmType algoType)
        {
            switch (algoType)
            {
                case HashAlgorithmType.None:
                    return null;
                case HashAlgorithmType.Md5:
                    return MD5.Create();
                case HashAlgorithmType.Sha1:
                    return SHA1.Create();
                case HashAlgorithmType.Sha256:
                    return SHA256.Create();
                case HashAlgorithmType.Sha384:
                    return SHA384.Create();
                case HashAlgorithmType.Sha512:
                    return SHA512.Create();
            }
            return null;
        }

        public static byte[] ComputeBytesHash(byte[] bytes, HashAlgorithmType algorithm =HashAlgorithmType.Md5)
        {
            if (bytes == null || bytes.Length == 0)
                return bytes;

            HashAlgorithm algo= CreateAlgoByType(algorithm);
            if (algo == null)
                return bytes;

            using (algo)
            {
                byte[] hashBytes= algo.ComputeHash(bytes);
                return hashBytes;
            }
        }

        public static string ComputeStringHash(string str, HashAlgorithmType algorithm = HashAlgorithmType.Md5)
        {
            if (string.IsNullOrEmpty(str))
                return str;
            byte[] bytes= Encoding.UTF8.GetBytes(str);
            byte[] hashedBytes= ComputeBytesHash(bytes, algorithm);
            // 将字节数组转换为字符串
            StringBuilder builder = new StringBuilder();
            foreach (var b in hashedBytes)
            {
                builder.Append(b.ToString("x2"));//每个字节转换为2个16进制字符
            }
            return builder.ToString();
        }

        public static int CombineHashCodes(int h1, int h2)
        {
            unchecked // 忽略溢出，这在计算哈希码时是可接受的
            {
                // 使用Bernstein的哈希算法来混合两个哈希码
                uint rol5 = ((uint)h1 << 5) | ((uint)h1 >> 27); // 循环左移5位
                return (int)(rol5 + h1 ^ h2);
            }
        }
    }
}